"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

from enum import unique
from django.db import models
from django.utils.translation import gettext_lazy as _
import random
import string
import functools

from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, get_enhavo
from main.models import SiriusoBazaAbstraktaKomunumoj, SiriusoBazaAbstraktaUzanto, SiriusoBazaAbstrakta
from main.models import SiriusoTipoAbstrakta
from uzantoj.models import UzantojAliro
from komunumoj.models import KomunumojAliro, Komunumo
from informiloj.models import InformilojLingvo


# Фотогалереи
# Типы файлов файлов изображений (фотографий), использует абстрактный класс SiriusoTipoAbstrakta
class FotojFotoDosieroTipo(SiriusoTipoAbstrakta):

    # название многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_fotoj_dosieroj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de dosieroj de bildoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de dosieroj de bildoj')


# Генерация случайного названия и переименование загружаемых картинок записей советов
def dosiero_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'fotoj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Файлы изображений (фотографий), использует абстрактный класс SiriusoBazaAbstraktaUzanto
class FotojFotoDosiero(SiriusoBazaAbstraktaUzanto):

    # тип файла
    tipo = models.ForeignKey(FotojFotoDosieroTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # связь с оригенальным изображением
    originalo = models.ForeignKey('self', verbose_name=_('Originala dosiero'), blank=True, default=None, null=True,
                                  on_delete=models.CASCADE)

    # исходное изображение
    bildo_baza = models.ImageField(_('Baza bildo'), upload_to=dosiero_nomo, blank=False, null=False)

    # Хэш базового файла
    hash = models.TextField(_('Hash'), max_length=64, blank=True, null=True)

    # изображение большого размера (размер до 1280x1024 включительно)
    bildo_a = models.ImageField(_('Granda bildo'), blank=True, null=False)

    # изображение среднего размера
    bildo_b = models.ImageField(_('Averaĝa bildo'), blank=True, null=True)

    # изображение малого размера
    bildo_c = models.ImageField(_('Malgranda bildo'), blank=True, null=True)

    # миниатюра фотографии
    bildo_d = models.ImageField(_('Miniaturo'), blank=True, null=True)

    # аватара или обложка
    bildo_e = models.ImageField(_('Avataro aŭ kovrilo'), blank=True, null=True)

    # малая аватара или обложка
    bildo_f = models.ImageField(_('Miniaturo avataro aŭ kovrilo'), blank=True, null=True)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_fotoj_dosieroj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dosiero de bildo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dosieroj de bildoj')
        # индексы
        indexes = [
            models.Index(fields=['hash',])
        ]

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)


# Фотогалереи пользователей
# Типы альбомов пользователей, использует абстрактный класс SiriusoTipoAbstrakta
class FotojAlbumoUzantoTipo(SiriusoTipoAbstrakta):

    # название многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_albumoj_uzantoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de albumoj de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de albumoj de uzantoj')


# Альбомы пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class FotojAlbumoUzanto(SiriusoBazaAbstraktaUzanto):

    # тип альбома
    tipo = models.ForeignKey(FotojAlbumoUzantoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # название многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # фото на обложку альбома
    kovrilo = models.ImageField(_('Foto de kovrilo'), blank=True, null=True)

    # исходная фотография на обложку альбома
    kovrilo_maks = models.ImageField(_('Maksimuma foto de kovrilo'), blank=True, null=True)

    # доступ к альбому
    aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              on_delete=models.CASCADE)

    # разрешено ли комментировать альбом и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_albumoj_uzantoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Albumo de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Albumoj de uzantoj')


# Фотографии (изображения) пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class FotojFotoUzanto(SiriusoBazaAbstraktaUzanto):

    # описание многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # альбом
    albumo = models.ForeignKey(FotojAlbumoUzanto, verbose_name=_('Albumo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # файлы изображения
    dosiero = models.ForeignKey(FotojFotoDosiero, verbose_name=_('Dosieroj'), blank=False, default=None,
                                on_delete=models.CASCADE)

    # разрешено ли комментировать фотографию и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_fotoj_uzantoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Foto de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Fotoj de uzantoj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto этой модели
        return '{}'.format(self.posedanto)


# Генерация случайного названия и переименование загружаемых картинок аватар пользователей
def uzantoj_avataro_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'uzantoj/avataroj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Аватары пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class FotojUzantojAvataro(SiriusoBazaAbstraktaUzanto):

    # главный вариант аватара для всех языковых версий (да или нет)
    chefa_varianto = models.BooleanField(_('Ĉefa varianto'), default=False)

    # активный аватар в рамках своей языковой версии (да или нет), неактивные можно будет просмотреть
    aktiva = models.BooleanField(_('Aktiva'), default=False)

    # основное изображение (размер 180x180)
    bildo = models.ImageField(_('Avataro'), upload_to=uzantoj_avataro_nomo, blank=False, default=None)

    # миниатюра (размер 50х50)
    bildo_min = models.ImageField(_('Miniaturo'), upload_to=uzantoj_avataro_nomo, blank=False, default=None)

    # исходное изображение
    bildo_maks = models.ImageField(_('Maksimuma bildo'), upload_to=uzantoj_avataro_nomo, blank=True, null=True)

    # Изображение из фотоальбома
    avataro = models.ForeignKey(FotojFotoUzanto, verbose_name=_('Bildo de la albumo'), blank=True,
                                related_name='%(app_label)s_%(class)s_avataro',
                                null=True, on_delete=models.CASCADE)

    # выбор языкового кода из справочника
    lingvo = models.ForeignKey(InformilojLingvo, verbose_name=_('Lingvo'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_lingvo',
                               on_delete=models.CASCADE)

    # разрешено ли комментировать изображение и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_uzantoj_avataroj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Avataro')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Avataroj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)


# Генерация случайного названия и переименование загружаемых картинок обложек пользователей
def uzantoj_kovrilo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'uzantoj/kovriloj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Обложки пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class FotojUzantojKovrilo(SiriusoBazaAbstraktaUzanto):

    # главный вариант обложки для всех языковых версий (да или нет)
    chefa_varianto = models.BooleanField(_('Ĉefa varianto'), default=False)

    # активная обложка в рамках своей языковой версии (да или нет), неактивные можно будет просмотреть
    aktiva = models.BooleanField(_('Aktiva'), default=False)

    # изображение (размер 820x200)
    bildo = models.ImageField(_('Kovrilo'), upload_to=uzantoj_kovrilo_nomo, blank=False, default=None)

    # исходное изображение
    bildo_maks = models.ImageField(_('Maksimuma bildo'), upload_to=uzantoj_kovrilo_nomo, blank=True, null=True)

    # Изображение из фотоальбома
    kovrilo = models.ForeignKey(FotojFotoUzanto, verbose_name=_('Bildo de la albumo'), blank=True,
                                related_name='%(app_label)s_%(class)s_kovrilo',
                                null=True, on_delete=models.CASCADE)

    # выбор языкового кода из справочника
    lingvo = models.ForeignKey(InformilojLingvo, verbose_name=_('Lingvo'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_lingvo',
                               on_delete=models.CASCADE)

    # разрешено ли комментировать изображение и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_uzantoj_kovriloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kovrilo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kovriloj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)


# Фотогалереи сообществ
# Типы альбомов сообществ, использует абстрактный класс SiriusoTipoAbstrakta
class FotojAlbumoKomunumoTipo(SiriusoTipoAbstrakta):

    # название многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_albumoj_komunumoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de albumoj de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de albumoj de komunumoj')


# Фотогалереи сообществ
# Альбомы сообществ, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class FotojAlbumoKomunumo(SiriusoBazaAbstraktaKomunumoj):

    # тип альбома
    tipo = models.ForeignKey(FotojAlbumoKomunumoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # название многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # фото на обложку альбома
    kovrilo = models.ImageField(_('Foto de kovrilo'), blank=True, null=True)

    # исходная фотография на обложку альбома
    kovrilo_maks = models.ImageField(_('Maksimuma foto de kovrilo'), blank=True, null=True)

    # доступ к альбому
    aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              related_name='%(app_label)s_%(class)s_aliro', on_delete=models.CASCADE)

    # разрешено ли комментировать альбом и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # владелец (сообщество)
    posedanto = models.ForeignKey(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_albumoj_komunumoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Albumo de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Albumoj de komunumoj')


# Фотографии сообществ, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class FotojFotoKomunumo(SiriusoBazaAbstraktaKomunumoj):

    # описание многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # альбом
    albumo = models.ForeignKey(FotojAlbumoKomunumo, verbose_name=_('Albumo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # владелец (сообщество)
    posedanto = models.ForeignKey(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  related_name='%(app_label)s_%(class)s_posedanto',
                                  on_delete=models.CASCADE)

    # файлы изображения
    dosiero = models.ForeignKey(FotojFotoDosiero, verbose_name=_('Dosieroj'), blank=False, default=None,
                                on_delete=models.CASCADE)

    # разрешено ли комментировать фотографию и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    def __str__(self):
        return '{} ({}): {}'.format(
            _('Foto'),
            get_enhavo(self.posedanto.nomo, empty_values=True)[0],
            self.uuid
        )

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_fotoj_komunumoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Foto de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Fotoj de komunumoj')


def komunumoj_bildo_nomo(instance, filename, tipo='avataroj'):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'komunumoj/{}/bildoj/{}.{}'.format(tipo, rnd_string, filename.split('.')[-1])


komunumoj_avataro_nomo = functools.partial(komunumoj_bildo_nomo, tipo='avataroj')
komunumoj_kovrilo_nomo = functools.partial(komunumoj_bildo_nomo, tipo='kovriloj')
komunumoj_informo_bildo_nomo = functools.partial(komunumoj_bildo_nomo, tipo='informoj')


# Аватары сообществ, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class FotojKomunumoAvataro(SiriusoBazaAbstraktaKomunumoj):
    # владелец
    posedanto = models.ForeignKey(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  related_name='%(app_label)s_%(class)s_posedanto',
                                  on_delete=models.CASCADE)

    # главный вариант аватара для всех языковых версий (да или нет)
    chefa_varianto = models.BooleanField(_('Ĉefa varianto'), default=False)

    # активный аватар в рамках своей языковой версии (да или нет), неактивные можно будет просмотреть
    aktiva = models.BooleanField(_('Aktiva'), default=False)

    # основное изображение (размер 90x90)
    bildo = models.ImageField(_('Avataro'), upload_to=komunumoj_avataro_nomo, blank=False, default=None)

    # миниатюра (размер 50х50)
    bildo_min = models.ImageField(_('Miniaturo'), upload_to=komunumoj_avataro_nomo, blank=False, default=None)

    # исходное изображение
    bildo_maks = models.ImageField(_('Maksimuma bildo'), upload_to=komunumoj_avataro_nomo, blank=True,
                                   null=True)

    # Изображение из фотоальбома
    avataro = models.ForeignKey(FotojFotoKomunumo, verbose_name=_('Bildo de la albumo'), blank=True,
                                null=True, on_delete=models.CASCADE)

    # выбор языкового кода из справочника
    lingvo = models.ForeignKey(InformilojLingvo, verbose_name=_('Lingvo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # разрешено ли комментировать изображение и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_komunumoj_avataroj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Avataro de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Avataroj de komunumo')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)


# Обложки сообществ, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class FotojKomunumoKovrilo(SiriusoBazaAbstraktaKomunumoj):
    # владелец
    posedanto = models.ForeignKey(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  related_name='%(app_label)s_%(class)s_posedanto',
                                  on_delete=models.CASCADE)

    # главный вариант обложки для всех языковых версий (да или нет)
    chefa_varianto = models.BooleanField(_('Ĉefa varianto'), default=False)

    # активная обложка в рамках своей языковой версии (да или нет), неактивные можно будет просмотреть
    aktiva = models.BooleanField(_('Aktiva'), default=False)

    # изображение (размер 820x200)
    bildo = models.ImageField(_('Kovrilo'), upload_to=komunumoj_kovrilo_nomo, blank=False, default=None)

    # исходное изображение
    bildo_maks = models.ImageField(_('Maksimuma bildo'), upload_to=komunumoj_kovrilo_nomo, blank=True,
                                   null=True)

    # Изображение из фотоальбома
    kovrilo = models.ForeignKey(FotojFotoKomunumo, verbose_name=_('Bildo de la albumo'), blank=True,
                                null=True, on_delete=models.CASCADE)

    # выбор языкового кода из справочника
    lingvo = models.ForeignKey(InformilojLingvo, verbose_name=_('Lingvo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # разрешено ли комментировать изображение и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'fotoj_komunumoj_kovriloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kovrilo de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kovriloj de komunumoj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)


